Skip to content

Fixing unstable GitConfig parsing#42

Merged
VISTALL merged 2 commits into
consulo:masterfrom
unv-unv:unstable-git-config-fix
Jun 1, 2026
Merged

Fixing unstable GitConfig parsing#42
VISTALL merged 2 commits into
consulo:masterfrom
unv-unv:unstable-git-config-fix

Conversation

@unv-unv

@unv-unv unv-unv commented May 31, 2026

Copy link
Copy Markdown
Contributor

Ini.entrySet returns randomly ordered collection of entries, so in case of two remotes (origin, upstream) one time there would be (origin, upstream), another time (upstream, origin). And since remotes are compared as lists, permutations are assumed as non-equal and produce infinite loop of git log updates. Fixing by wrapping Ini with a sorted map (TreeMap).

…red collection of entries, so in case of two remotes (origin, upstream) one time there would be (origin, upstream), another time (upstream, origin). And since remotes are compared as lists, permutations are assumed as non-equal and produce infinite loop of git log updates. Fixing by wrapping Ini with a sorted map (TreeMap).
@unv-unv

unv-unv commented Jun 1, 2026

Copy link
Copy Markdown
Contributor Author

@claude review pr with inline comments

@github-actions

github-actions Bot commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Claude finished @unv-unv's task in 2m 58s —— View job


Review: Fixing unstable GitConfig parsing

  • Gather context (diff, GitConfig.java, GitConfigHelper.java)
  • Analyze the fix
  • Post inline review comments
  • Final summary

Verdict: looks good. This is a solid root-cause fix. Ini.entrySet() had no ordering guarantee, so the parsed myRemotes list could come out as [origin, upstream] or [upstream, origin] between reads. Since GitConfig equality compares remotes as ordered lists, the two permutations registered as "not equal" and triggered an endless git-log refresh loop. Wrapping the parsed sections in a TreeMap makes iteration order deterministic and breaks the loop. The drive-by swap of assert remote != null for Objects.requireNonNull(...) (GitConfig.java:82) is also a nice improvement, since assert is off by default at runtime.

I left 2 inline comments:

  • GitConfig.java:140 — minor: a double blank line was introduced; included a one-click suggestion to collapse it.
  • GitConfig.java:134 — non-blocking notes: TreeMap (alphabetical) vs LinkedHashMap (file order) as a behavioral choice, and a heads-up that copying ini4j's MultiMap into a plain Map collapses duplicate section keys (an edge case real .git/config files don't hit).

None of these block merging — the only actionable item is the cosmetic blank-line nit.
· branch unstable-git-config-fix

return emptyConfig;
}


Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: the fix leaves a double blank line here — the original already had one blank line after the catch block, and this adds another. Worth collapsing back to a single blank line.

Suggested change
Pair<Collection<Remote>, Collection<Url>> remotesAndUrls = parseRemotes(ini, GitConfig.class.getClassLoader());

SortedMap<String, Profile.Section> ini;
try {
ini = GitConfigHelper.loadIniFile(configFile);
ini = new TreeMap<>(GitConfigHelper.loadIniFile(configFile));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good root-cause fix — wrapping in a TreeMap makes section iteration order deterministic, so two remotes (e.g. origin/upstream) always parse into the same list order and the equality check no longer flip-flops, which is what was driving the infinite git-log refresh loop.

Two notes for consideration (both non-blocking):

  1. TreeMap vs LinkedHashMapTreeMap sorts sections alphabetically, which is perfectly deterministic and fine here. If you'd prefer to preserve the on-disk .git/config order, new LinkedHashMap<>(GitConfigHelper.loadIniFile(configFile)) is equally deterministic. Either is correct; just flagging the behavioral choice.

  2. ini4j Ini is a MultiMap — copying it into a plain Map collapses any duplicate section keys to a single entry (last wins), whereas Ini.get() returns the first. Real .git/config files don't repeat a section name, so this is only an edge case, but worth being aware of.

@VISTALL VISTALL merged commit 074a095 into consulo:master Jun 1, 2026
1 check passed
@unv-unv unv-unv deleted the unstable-git-config-fix branch June 1, 2026 10:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants